/**
 * Copyright &copy; 2018 thinkis All rights reserved.
 */
package com.thinkis.modules.sys.service;

import com.thinkis.common.persistence.Page;
import com.thinkis.common.service.CrudService;
import com.thinkis.modules.sys.dao.ScheduleDao;
import com.thinkis.modules.sys.entity.Schedule;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 系统定时任务Service
 * @author jauddy
 * @version 2019-07-05
 */
@Service
@Transactional(readOnly = true)
public class ScheduleService extends CrudService<ScheduleDao, Schedule> {

    @Autowired
    private Scheduler scheduler;

	public Schedule get(String id) {
		return super.get(id);
	}
	
	public List<Schedule> findList(Schedule schedule) {
		return super.findList(schedule);
	}
	
	public Page<Schedule> findPage(Page<Schedule> page, Schedule schedule) {
		return super.findPage(page, schedule);
	}
	
	@Transactional(readOnly = false)
	public int batchDelete(String selectedIds){
		int success = 0;
		try{
			String[] ids = selectedIds.split(",");
			for(String id : ids){
				Schedule schedule = new Schedule();
				schedule.setId(id);
				delete(schedule);
				success++;
			}
		}catch(Exception e){
			logger.error("数据删除失败");
			return success;
		}
		return success;
	}
    @Transactional(readOnly = false)
    public void save(Schedule schedule) {
        if (!schedule.getIsNewRecord()) {
            Schedule t = this.get(schedule.getId());
            JobKey key = new JobKey(t.getName(), t.getTGroup());
            try {
                scheduler.deleteJob(key);
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
        this.add(schedule);
        super.save(schedule);
    }


    @Transactional(readOnly = false)
    public void add(Schedule schedule){
        Class job = null;
        try {
            job = Class.forName(schedule.getClassname());
        } catch (ClassNotFoundException e1) {
            e1.printStackTrace();
        }
        JobDetail jobDetail = JobBuilder.newJob(job).withIdentity(schedule.getName(), schedule.getTGroup())
                .build();
        jobDetail.getJobDataMap().put("schedule", schedule);

        // 表达式调度构建器（可判断创建SimpleScheduleBuilder）
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(schedule.getExpression());

        // 按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(schedule.getName(), schedule.getTGroup()).withSchedule(scheduleBuilder).build();
        try {
            scheduler.scheduleJob(jobDetail, trigger);
            JobKey key = new JobKey(schedule.getName(), schedule.getTGroup());
            if(schedule.getStatus().equals("0")){
                scheduler.pauseJob(key);
            }else{
                scheduler.resumeJob(key);
            }

        } catch (SchedulerException e) {
            e.printStackTrace();
        }

    }

    @Transactional(readOnly = false)
    public void delete(Schedule schedule) {

        JobKey key = new JobKey(schedule.getName(), schedule.getTGroup());
        try {
            scheduler.deleteJob(key);
            super.delete(schedule);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }


    }


    /**
     * 获取所有JobDetail
     * @return 结果集合
     */
    public List<JobDetail> getJobs() {
        try {
            GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            List<JobDetail> jobDetails = new ArrayList<JobDetail>();
            for (JobKey key : jobKeys) {
                jobDetails.add(scheduler.getJobDetail(key));
            }
            return jobDetails;
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取所有计划中的任务
     * @return 结果集合
     */
    public List<Schedule> getAllSchedule(){
        List<Schedule> scheduleList=new ArrayList<Schedule>();;
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        try {
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    Schedule schedule = new Schedule();
                    schedule.setName(jobKey.getName());
                    schedule.setTGroup(jobKey.getGroup());
                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    schedule.setStatus(triggerState.name());
                    //获取要执行的定时任务类名
                    JobDetail jobDetail=scheduler.getJobDetail(jobKey);
                    schedule.setClassname(jobDetail.getJobClass().getName());
                    //判断trigger
                    if (trigger instanceof SimpleTrigger) {
                        SimpleTrigger simple = (SimpleTrigger) trigger;
                        schedule.setExpression("重复次数:"+ (simple.getRepeatCount() == -1 ?
                                "无限" : simple.getRepeatCount()) +",重复间隔:"+(simple.getRepeatInterval()/1000L));
                        schedule.setDescription(simple.getDescription());
                    }
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cron = (CronTrigger) trigger;
                        schedule.setExpression(cron.getCronExpression());
                        schedule.setDescription(cron.getDescription()==null?("触发器:" + trigger.getKey()):cron.getDescription());
                    }
                    scheduleList.add(schedule);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return scheduleList;
    }

    /**
     * 获取所有运行中的任务
     * @return 结果集合
     */
    public List<Schedule> getAllRuningSchedule(){
        List<Schedule> scheduleList=null;
        try {
            List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
            scheduleList = new ArrayList<Schedule>(executingJobs.size());
            for (JobExecutionContext executingJob : executingJobs) {
                Schedule schedule = new Schedule();
                JobDetail jobDetail = executingJob.getJobDetail();
                JobKey jobKey = jobDetail.getKey();
                Trigger trigger = executingJob.getTrigger();
                schedule.setName(jobKey.getName());
                schedule.setTGroup(jobKey.getGroup());
                //schedule.setDescription("触发器:" + trigger.getKey());
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                schedule.setStatus(triggerState.name());
                //获取要执行的定时任务类名
                schedule.setClassname(jobDetail.getJobClass().getName());
                //判断trigger
                if (trigger instanceof SimpleTrigger) {
                    SimpleTrigger simple = (SimpleTrigger) trigger;
                    schedule.setExpression("重复次数:"+ (simple.getRepeatCount() == -1 ?
                            "无限" : simple.getRepeatCount()) +",重复间隔:"+(simple.getRepeatInterval()/1000L));
                    schedule.setDescription(simple.getDescription());
                }
                if (trigger instanceof CronTrigger) {
                    CronTrigger cron = (CronTrigger) trigger;
                    schedule.setExpression(cron.getCronExpression());
                    schedule.setDescription(cron.getDescription());
                }
                scheduleList.add(schedule);
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return scheduleList;
    }

    /**
     * 获取所有的触发器
     * @return 结果集合
     */
    public List<Schedule> getTriggersInfo(){
        try {
            GroupMatcher<TriggerKey> matcher = GroupMatcher.anyTriggerGroup();
            Set<TriggerKey> Keys = scheduler.getTriggerKeys(matcher);
            List<Schedule> triggers = new ArrayList<Schedule>();

            for (TriggerKey key : Keys) {
                Trigger trigger = scheduler.getTrigger(key);
                Schedule schedule = new Schedule();
                schedule.setName(trigger.getJobKey().getName());
                schedule.setTGroup(trigger.getJobKey().getGroup());
                schedule.setStatus(scheduler.getTriggerState(key)+"");
                if (trigger instanceof SimpleTrigger) {
                    SimpleTrigger simple = (SimpleTrigger) trigger;
                    schedule.setExpression("重复次数:"+ (simple.getRepeatCount() == -1 ?
                            "无限" : simple.getRepeatCount()) +",重复间隔:"+(simple.getRepeatInterval()/1000L));
                    schedule.setDescription(simple.getDescription());
                }
                if (trigger instanceof CronTrigger) {
                    CronTrigger cron = (CronTrigger) trigger;
                    schedule.setExpression(cron.getCronExpression());
                    schedule.setDescription(cron.getDescription());
                }
                triggers.add(schedule);
            }
            return triggers;
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 暂停任务
     */
    @Transactional(readOnly = false)
    public void stopJob(Schedule schedule){

        JobKey key = new JobKey(schedule.getName(), schedule.getTGroup());
        try {
            scheduler.pauseJob(key);
            schedule.setStatus("0");
            super.save(schedule);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 恢复任务
     */
    @Transactional(readOnly = false)
    public void restartJob(Schedule schedule){
        JobKey key = new JobKey(schedule.getName(), schedule.getTGroup());
        try {
            scheduler.resumeJob(key);
            schedule.setStatus("1");
            super.save(schedule);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 立马执行一次任务
     */
    @Transactional(readOnly = false)
    public void startNowJob(Schedule schedule){
        JobKey key = new JobKey(schedule.getName(), schedule.getTGroup());
        try {
            scheduler.triggerJob(key);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }


    /**
     * 修改触发器时间
     * @param name 任务名
     * @param group 任务组
     * @param cron cron表达式
     */
    @Transactional(readOnly = false)
    public void modifyTrigger(String name,String group,String cron){
        try {
            TriggerKey key = TriggerKey.triggerKey(name, group);
            //Trigger trigger = scheduler.getTrigger(key);

            CronTrigger newTrigger = (CronTrigger) TriggerBuilder.newTrigger()
                    .withIdentity(key)
                    .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                    .build();
            scheduler.rescheduleJob(key, newTrigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

    }

    /**
     * 暂停调度器
     */
    @Transactional(readOnly = false)
    public void stopScheduler(){
        try {
            if (!scheduler.isInStandbyMode()) {
                scheduler.standby();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}